package net.simpleframework.swing;

import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Arrays;
import java.util.Vector;

import javax.swing.DefaultListModel;
import javax.swing.JCheckBox;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;

import net.simpleframework.util.ConvertUtils;

import org.jdesktop.swingx.JXList;

/**
 * 这是一个开源的软件，请在LGPLv3下合法使用、修改或重新发布。
 * 
 * @author 陈侃(cknet@126.com, 13910090885)
 *         http://code.google.com/p/simpleframework/
 *         http://www.simpleframework.net
 */
public class JCheckBoxList extends JXList {
	{
		setCellRenderer(new ListCellRenderer() {
			final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);

			final JCheckBox jcb = new JCheckBox();
			{
				jcb.setOpaque(true);
				jcb.setBorder(noFocusBorder);
			}

			@Override
			public Component getListCellRendererComponent(final JList list, final Object value,
					final int index, final boolean isSelected, final boolean cellHasFocus) {
				if (isSelected) {
					jcb.setBackground(list.getSelectionBackground());
					jcb.setForeground(list.getSelectionForeground());
				} else {
					jcb.setBackground(list.getBackground());
					jcb.setForeground(list.getForeground());
				}
				if (value instanceof Entry) {
					final Entry entry = (Entry) value;
					jcb.setSelected(entry.isChecked());
					jcb.setText(entry.getValue().toString());
				} else {
					jcb.setSelected(false);
					jcb.setText(ConvertUtils.toString(value));
				}

				jcb.setEnabled(list.isEnabled());
				jcb.setFont(list.getFont());
				jcb.setBorder((cellHasFocus) ? UIManager.getBorder("List.focusCellHighlightBorder")
						: noFocusBorder);
				return jcb;
			}
		});

		addMouseListener(new MouseAdapter() {
			private int indexSelected = -1;

			@Override
			public void mouseExited(final MouseEvent e) {
				indexSelected = -1;
			}

			@Override
			public void mousePressed(final MouseEvent e) {
				indexSelected = locationToIndex(e.getPoint());
				if (indexSelected >= getModel().getSize()) {
					indexSelected = -1;
				}
				if (isEnabled() && (e.getX() < 12) && (indexSelected >= 0)) {
					final Entry entry = getEntry(indexSelected);
					entry.setChecked(!entry.checked);
					repaint();
				}
			}

			@Override
			public void mouseReleased(final MouseEvent e) {
				indexSelected = -1;
			}
		});
	}

	public JCheckBoxList(final Entry[] items) {
		this(new Vector<Entry>(Arrays.asList(items)));
	}

	public JCheckBoxList() {
		this(new Vector<Entry>());
	}

	public JCheckBoxList(final Vector<Entry> items) {
		final DefaultListModel lm = new DefaultListModel();
		for (final Entry entry : items) {
			lm.addElement(entry);
		}
		setModel(lm);
	}

	public void addItem(final boolean check, final Object value) {
		final DefaultListModel lm = (DefaultListModel) getModel();
		lm.addElement(new Entry(check, value));
	}

	public Entry getEntry(final int index) {
		return (Entry) ((DefaultListModel) getModel()).getElementAt(index);
	}

	public static class Entry {
		private boolean checked;

		private final Object value;

		Entry(final boolean checked, final Object value) {
			this.checked = checked;
			this.value = value;
		}

		public Object getValue() {
			return value;
		}

		public boolean isChecked() {
			return checked;
		}

		public void setChecked(final boolean checked) {
			this.checked = checked;
		}
	}

	private static final long serialVersionUID = -2284712298812158942L;
}
